using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.Generic;

namespace devtm.Aop.InternalProcess
{
	public static class ExpressionExtension
	{

        public static IEnumerable<MethodInfo> GetMemberOfExpression<T>(this Expression<Func<T, object>> exp)
        {
            switch (exp.Body.NodeType)
            {

                case ExpressionType.Call:
                    yield return ((MethodCallExpression)exp.Body).Method;
                    break;

                case ExpressionType.MemberAccess:
                    PropertyInfo p = (exp.Body as MemberExpression).Member as PropertyInfo;
                    yield return p.GetGetMethod();
                    yield return p.GetSetMethod();
                    break;

                case ExpressionType.Convert:
                    var unaryExp = exp.Body as UnaryExpression;
                    Confirm.Assertion(unaryExp.Operand is MemberExpression, "Property expected: " + unaryExp.Operand.ToString());
                    yield return ((exp.Body as UnaryExpression).Operand as MemberExpression).Member as MethodInfo;
                    break;

                default: 
                    throw new ArgumentException("Property expected", exp.Body.ToString());
            }
        }

        public static IEnumerable<MethodInfo> GetMemberOfExpression<T>(this Expression<Action<T>> exp)
        {
            switch (exp.Body.NodeType)
            {

                case ExpressionType.Call:
                    yield return ((MethodCallExpression)exp.Body).Method;
                    break;

                case ExpressionType.MemberAccess:
                    PropertyInfo p = (exp.Body as MemberExpression).Member as PropertyInfo;
                    yield return p.GetGetMethod();
                    yield return p.GetSetMethod();
                    break;

                case ExpressionType.Convert:
                    var unaryExp = exp.Body as UnaryExpression;
                    Confirm.Assertion(unaryExp.Operand is MemberExpression, "Property expected: " + unaryExp.Operand.ToString());
                    yield return ((exp.Body as UnaryExpression).Operand as MemberExpression).Member as MethodInfo;
                    break;

                default:
                    throw new ArgumentException("Property expected", exp.Body.ToString());
            }
        }

	}
}
